package com.liezh.allholloworld.itext7;

import com.itextpdf.kernel.geom.LineSegment;
import com.itextpdf.kernel.geom.Vector;
import com.itextpdf.kernel.pdf.canvas.parser.listener.ITextChunkLocation;

/**
 * @author liezh
 * @date 2022-1-13
 */
public class MyITextChunkLocation implements ITextChunkLocation {
    private final Vector startLocation;
    private final Vector endLocation;
    private final Vector orientationVector;
    private final int orientationMagnitude;
    private final int distPerpendicular;
    private final float distParallelStart;
    private final float distParallelEnd;
    private final float charSpaceWidth;

    public MyITextChunkLocation(Vector startLocation, Vector endLocation, float charSpaceWidth) {
        this.startLocation = startLocation;
        this.endLocation = endLocation;
        this.charSpaceWidth = charSpaceWidth;
        Vector oVector = endLocation.subtract(startLocation);
        if (oVector.length() == 0.0F) {
            oVector = new Vector(1.0F, 0.0F, 0.0F);
        }

        this.orientationVector = oVector.normalize();
        this.orientationMagnitude = (int)(Math.atan2((double)this.orientationVector.get(1), (double)this.orientationVector.get(0)) * 1000.0D);
        Vector origin = new Vector(0.0F, 0.0F, 1.0F);
        this.distPerpendicular = (int)startLocation.subtract(origin).cross(this.orientationVector).get(2);
        this.distParallelStart = this.orientationVector.dot(startLocation);
        this.distParallelEnd = this.orientationVector.dot(endLocation);
    }

    public int orientationMagnitude() {
        return this.orientationMagnitude;
    }

    public int distPerpendicular() {
        return this.distPerpendicular;
    }

    public float distParallelStart() {
        return this.distParallelStart;
    }

    public float distParallelEnd() {
        return this.distParallelEnd;
    }

    public Vector getStartLocation() {
        return this.startLocation;
    }

    public Vector getEndLocation() {
        return this.endLocation;
    }

    public float getCharSpaceWidth() {
        return this.charSpaceWidth;
    }

    public boolean sameLine(ITextChunkLocation as) {
        if (this.orientationMagnitude() != as.orientationMagnitude()) {
            return false;
        } else {
            float distPerpendicularDiff = (float)(this.distPerpendicular() - as.distPerpendicular());
            if (distPerpendicularDiff == 0.0F) {
                return true;
            } else {
                LineSegment mySegment = new LineSegment(this.startLocation, this.endLocation);
                LineSegment otherSegment = new LineSegment(as.getStartLocation(), as.getEndLocation());
                return Math.abs(distPerpendicularDiff) <= 2.0F && (mySegment.getLength() == 0.0F || otherSegment.getLength() == 0.0F);
            }
        }
    }

    public float distanceFromEndOf(ITextChunkLocation other) {
        return this.distParallelStart() - other.distParallelEnd();
    }

    public boolean isAtWordBoundary(ITextChunkLocation previous) {
        if (!this.startLocation.equals(this.endLocation) && !previous.getEndLocation().equals(previous.getStartLocation())) {
            float dist = this.distanceFromEndOf(previous);
            if (dist < 0.0F) {
                dist = previous.distanceFromEndOf(this);
                if (dist < 0.0F) {
                    return false;
                }
            }

            return dist > this.getCharSpaceWidth() / 2.0F;
        } else {
            return false;
        }
    }

    static boolean containsMark(ITextChunkLocation baseLocation, ITextChunkLocation markLocation) {
        return baseLocation.getStartLocation().get(0) <= markLocation.getStartLocation().get(0) && baseLocation.getEndLocation().get(0) >= markLocation.getEndLocation().get(0) && (float)Math.abs(baseLocation.distPerpendicular() - markLocation.distPerpendicular()) <= 2.0F;
    }
}
